package net.lzzy.practices.services;

import net.lzzy.practices.entities.Applicant;
import net.lzzy.practices.entities.Course;
import net.lzzy.practices.entities.User;
import net.lzzy.practices.repositonies.ApplicantRepository;
import net.lzzy.practices.repositonies.CourseRepository;
import net.lzzy.practices.repositonies.UserRepository;
import net.lzzy.practices.utils.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.UUID;

/**
 * @author m
 */
@Service
public class ApplicantServiceImpl implements ApplicantService{
    private  final ApplicantRepository repository;
    private final CourseRepository cRepository;

    private final UserRepository uRepository;
@Autowired
    public ApplicantServiceImpl(ApplicantRepository repository, CourseRepository cRepository, UserRepository uRepository) {
        this.repository = repository;
        this.cRepository = cRepository;
        this.uRepository = uRepository;
    }


    /**
     * @param studentId
     * @param courseId
     * @param token
     * @return
     */
    @Override
    public Applicant apply(UUID studentId, UUID courseId, String token) {
        //验证是否有权限
        if(!studentId.toString().equals(JwtUtil.verifyToken(token))) {
            return null;
        }
        User stuent= uRepository.findById(studentId).orElse(null);
        if(stuent==null) {
            return null;
        }
        Course course=cRepository.findById(courseId).orElse(null);
        if(course==null){
            return  null;
        }
        Applicant applicant= new Applicant();
        applicant.setStudent(stuent);
        applicant.setCourse(course);
        applicant.setStatus(Applicant.STATUS_APPLYING);
        return  repository.save(applicant);


    }

    /**
     * 获取所有课程
     *
     * @param student
     * @param token
     * @return
     */
    @Override
    public List<Applicant> getAllCourses(UUID student, String token) {
        if(!student.toString().equals(JwtUtil.verifyToken(token))) {
            return null;
        }
        return  repository.findApplicantsByStudentIdEqualsOrderByApplyTimeDesc(student);
    }

    /**
     * @param student
     * @param token
     * @return
     */
    @Override
    public List<Applicant> getApplyingCourses(UUID student, String token) {
        if(!student.toString().equals(JwtUtil.verifyToken(token))) {
            return null;
        }

        return  repository.findApplicantsByStudentIdEqualsAndStatusEqualsOrderByApplyTimeDesc(student,Applicant.STATUS_APPLYING);
    }

    /**
     * @param student
     * @param token
     * @return
     */
    @Override
    public List<Applicant> getEnrolledCourses(UUID student, String token) {
        if(!student.toString().equals(JwtUtil.verifyToken(token))) {
            return null;
        }
        return repository.findApplicantsByStudentIdEqualsAndStatusEqualsOrderByApplyTimeDesc(student,Applicant.STATUS_APPROVED);
    }

    /**
     * //获取申请不通过的课程
     *
     * @param student
     * @param token
     * @return
     */
    @Override
    public List<Applicant> getDeclinedCourses(UUID student, String token) {
        if(!student.toString().equals(JwtUtil.verifyToken(token))) {
            return null;
        }
        return  repository.findApplicantsByStudentIdEqualsAndStatusEqualsOrderByApplyTimeDesc(student,Applicant.STATUS_DECLINED);
    }
    private  Applicant update(UUID applincanId,String token,int status){
        Applicant applicant= repository.findById(applincanId).orElse(null);
        if(applicant==null){
            return null;
        }
        Course course = applicant.getCourse();
        UUID teacherId= course.getTeacher().getId();
        if(!teacherId.toString().equals(JwtUtil.verifyToken(token))){
            return  null;
        }
        applicant.setStatus(status);
        return  repository.save(applicant);

    }

    /**
     * @param applicantId
     * @param token
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Applicant approve(UUID applicantId, String token) {
        Applicant applicant= update(applicantId,token,Applicant.STATUS_APPROVED);
        if(applicant!=null){
            Course course= applicant.getCourse();
            User student= applicant.getStudent();
            List<User> students = course.getStudents();
            if(!students.contains(student)){
                students.add(student);
            }
            course.setStudents(students);
            applicant.setCourse(cRepository.save(course));
        }


        return applicant;
    }


    /**
     * @param applicantId
     * @param token
     * @return
     */
    @Override
    public Applicant decline(UUID applicantId, String token) {
        return update(applicantId,token,Applicant.STATUS_APPLYING);
    }
    private  List<Applicant> getStudents(UUID courseId,String token,int status){
        Course course= cRepository.findById(courseId).orElse(null);
        if(course==null)
            return null;
        UUID teacherId=course.getTeacher().getId();
        if(!teacherId.toString().equals(JwtUtil.verifyToken(token)))
            return  null;
        return repository.findApplicantsByCourseIdEqualsAndStatusEqualsOrderByApplyTimeDesc(courseId,status);
    }

    /**
     * @param courseId
     * @param token
     * @return
     */
    @Override
    public List<Applicant> getEnrolledStudents(UUID courseId, String token) {
        return getStudents(courseId,token,Applicant.STATUS_APPROVED);
    }

    /**
     * @param courseId
     * @param token
     * @return
     */
    @Override
    public List<Applicant> getApplyingStudents(UUID courseId, String token) {
        return getStudents(courseId,token,Applicant.STATUS_APPLYING);
    }

    /**
     * @param courseId
     * @param token
     * @return
     */
    @Override
    public List<Applicant> getDeclinedStudents(UUID courseId, String token) {
        return getStudents(courseId,token,Applicant.STATUS_DECLINED);
    }

    /**
     * @param studentId
     * @param token
     * @return
     */

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Course removeStudent(UUID courseId,UUID studentId, String token) {
        Course course= cRepository.findById(courseId).orElse(null);
        if(course==null){
            return null;
        }
        UUID teacherId= course.getTeacher().getId();
        if(!teacherId.toString().equals(JwtUtil.verifyToken(token))){
            return  null;
        }
        course.getStudents().removeIf(s->s.getId().equals(studentId));
        Applicant applicant = repository.findApplicantsByCourseIdEqualsAndStudentIdEquals(courseId,studentId);
            if(applicant!=null)
            {
              applicant.setStatus(Applicant.STATUS_DECLINED);
              repository.save(applicant);
            }

        return cRepository.save(course);
    }
}
